package compilationunit;


import java.io.*;
import java.util.Queue;
import java.util.*;

public class Parser {
	static final int _EOF = 0;
	static final int _ident = 1;
	static final int _enteros = 2;
	static final int _cadenaCar = 3;
	static final int _boolean = 4;
	static final int _char = 5;
	static final int _class = 6;
	static final int _false = 7;
	static final int _int = 8;
	static final int _new = 9;
	static final int _short = 10;
	static final int _static = 11;
	static final int _true = 12;
	static final int _void = 13;
	static final int _dosPuntos = 14;
	static final int _comma = 15;
	static final int _punto = 16;
	static final int _llaveIzda = 17;
	static final int _corcheteIzda = 18;
	static final int _parentesisIzda = 19;
	static final int _menos = 20;
	static final int _not = 21;
	static final int _mas = 22;
	static final int _llaveDer = 23;
	static final int _corcheteDer = 24;
	static final int _parentesisDer = 25;
	static final int _multiplicacion = 26;
	static final int _div = 27;
	static final int _menor = 28;
	static final int _mayor = 29;
	static final int _igual = 30;
	static final int _puntoComa = 31;
	static final int _doblesComillas = 32;
	static final int _interrogacion = 33;
	static final int maxT = 41;

	static final boolean T = true;
	static final boolean x = false;
	static final int minErrDist = 2;

	public static Token token;    // last recognized token   /* pdt */
	public static Token la;       // lookahead token
	static int errDist = minErrDist;

    static TablaSimbolos tablasimbolos = new TablaSimbolos();
    static Simbolo simbolo = new Simbolo();
    static Simbolo simbolo_aux = new Simbolo();
    static Simbolo simbolo_aux2 = new Simbolo();
    static Argumento argumento;
    static Queue<Argumento> colaArgumento = new LinkedList<Argumento> ();


    static char tipo_asig = '-';
    static int num_args;
    static boolean vengode_decl_corch = false;
    static boolean vengode_decl_parent = false;
    static boolean vengode_arg_declaracion = false;


	static void SynErr (int n) {
		if (errDist >= minErrDist) Errors.SynErr(la.line, la.col, n);
		errDist = 0;
	}

	public static void SemErr (String msg) {
		if (errDist >= minErrDist) Errors.Error(token.line, token.col, msg); /* pdt */
		errDist = 0;
	}

	public static void SemError (String msg) {
		if (errDist >= minErrDist) Errors.Error(token.line, token.col, msg); /* pdt */
		errDist = 0;
	}

	public static void Warning (String msg) { /* pdt */
		if (errDist >= minErrDist) Errors.Warn(token.line, token.col, msg);
		errDist = 0;
	}

	public static boolean Successful() { /* pdt */
		return Errors.count == 0;
	}

	public static String LexString() { /* pdt */
		return token.val;
	}

	public static String LookAheadString() { /* pdt */
		return la.val;
	}

        static void Esperado (int n){
        Expect(n);
        //Para cargar un nuevo token se usa este metodo
        //y dado que sólo hay un simbolo (global), este metodo se encarga de
        //llenar de basura sus campos para que no se lean valores del token anterior.

        simbolo.setPos(token.pos);     // token position in the source text (starting at 0)
        simbolo.setCol(token.col);     // token column (starting at 0)
        simbolo.setLinea(token.line);    // token line (starting at 1)
        simbolo.setId(token.val);
        simbolo.setClaseRelacionada("");
        simbolo.setColaArgumentos(null);
        simbolo.setNumArgMetodo(-1);
        simbolo.setPublico(false);
        simbolo.setTamano(-1);
        simbolo.setTipo('-');
        simbolo.setTipoEnVector('-');
        simbolo.setTipoRetorno('-');
        simbolo.setInicializado(false);

    }

        static void Inicializa_aux(){

            try{
        simbolo_aux.setPos(-1);     // token position in the source text (starting at 0)
        simbolo_aux.setCol(-1);     // token column (starting at 0)
        simbolo_aux.setLinea(-1);    // token line (starting at 1)
        simbolo_aux.setId("");
        simbolo_aux.setClaseRelacionada("");
        simbolo_aux.setColaArgumentos(null);
        simbolo_aux.setNumArgMetodo(-1);
        simbolo_aux.setPublico(false);
        simbolo_aux.setTamano(-1);
        simbolo_aux.setTipo('-');
        simbolo_aux.setTipoEnVector('-');
        simbolo_aux.setTipoRetorno('-');
        simbolo_aux.setInicializado(false);
            }catch(NullPointerException e){
                simbolo_aux = new Simbolo();
            }
        
        }


	static void Get () {
		for (;;) {
			token = la; /* pdt */
			la = Scanner.Scan();
			if (la.kind <= maxT) { ++errDist; break; }

			la = token; /* pdt */
		}
	}

	static void Expect (int n) {
		if (la.kind==n) Get(); else { SynErr(n); }
	}

	static boolean StartOf (int s) {
		return set[s][la.kind];
	}

	static void ExpectWeak (int n, int follow) {
		if (la.kind == n) Get();
		else {
			SynErr(n);
			while (!StartOf(follow)) Get();
		}
	}

	static boolean WeakSeparator (int n, int syFol, int repFol) {
		boolean[] s = new boolean[maxT+1];
		if (la.kind == n) { Get(); return true; }
		else if (StartOf(repFol)) return false;
		else {
			for (int i=0; i <= maxT; i++) {
				s[i] = set[syFol][i] || set[repFol][i] || set[0][i];
			}
			SynErr(n);
			while (!s[la.kind]) Get();
			return StartOf(syFol);
		}
	}

	static void compilationunit() {
		while (la.kind == 6) {
			Clases();
		}
	}

	static void Clases() {
		Esperado(6);
		Esperado(1);
        simbolo.setTipo('x');
        int existe = tablasimbolos.InsertarSimbolo(simbolo, simbolo.getId());
        if (existe != 0) SemError("Nombre de clase repetido");
        tablasimbolos.CrearTablaPadre(simbolo.getId());
		Esperado(17);
		Miembros();
		Esperado(23);
	}

	static void TiposSimples() {
		if (la.kind == 8) {
            simbolo_aux.setTipo('e');
            simbolo_aux.setTipoEnVector('e');
            simbolo_aux.setTipoRetorno('e');
            simbolo_aux.setTamano(4);
			Get();
		} else if (la.kind == 4) {
            simbolo_aux.setTipo('b');
            simbolo_aux.setTipoEnVector('b');
            simbolo_aux.setTipoRetorno('b');
            simbolo_aux.setTamano(1);
			Get();
		} else if (la.kind == 13) {
             simbolo_aux.setTipoRetorno('n');
			Get();
		} else SynErr(42);
	}


//    Declaraciones = ["public" | "private"] TiposSimples (ident | "main") [";" | "["enteros"]" [";"] | "(" ["void" |ArgumentosDeclaracion] ")""{"Miembros"}"]


	static void Declaraciones() {
        Inicializa_aux();
		if (la.kind == 34 || la.kind == 35) {
			if (la.kind == 34) {
                simbolo_aux.setPublico(true);
				Get();
			} else {
				Get();
			}
		}
		TiposSimples();

		if (la.kind == 1) {
            simbolo_aux.setId(la.val);
            simbolo_aux.setCol(la.col);
            simbolo_aux.setPos(la.pos);
            simbolo_aux.setLinea(la.line);
            Get();
		} else if (la.kind == 36) {
            simbolo_aux.setId(la.val);
            simbolo_aux.setCol(la.col);
            simbolo_aux.setPos(la.pos);
            simbolo_aux.setLinea(la.line);
            if (!simbolo_aux.getPublico())
                SemErr("Falta modificador \"public\" en metodo main");
            tablasimbolos.setExisteMain(true);
			Get();
		} else SynErr(43);
		if (la.kind == 18 || la.kind == 19 || la.kind == 31) {
			if (la.kind == 31) {
                simbolo_aux.setTipoEnVector('-');
                simbolo_aux.setTipoRetorno('-');
                if (simbolo_aux.getId() == "main")
                    SynErr(25);
                int existe = tablasimbolos.InsertarSimbolo(simbolo_aux, simbolo_aux.getId());
                if (existe != 0) SemErr("Ya existe el identificador");
                Get();
			  } else if (la.kind == 18) {
                  simbolo_aux.setTipoRetorno('-');
                  simbolo_aux.setTipo('v');
                  if (simbolo_aux.getId() == "main")
                    SynErr(25);
                Get();
				Esperado(2);
                if (!token.val.equals("[") ){
                int entero = Integer.valueOf(token.val).intValue();
                if (entero < 0)
                    SemError("Imposible crear vector de tamaño negativo");
                simbolo_aux.setNumArgMetodo(entero);
                simbolo_aux.setTamano(entero * simbolo_aux.getTamano());
                }
				Esperado(24);
				Esperado(31);
                int existe = tablasimbolos.InsertarSimbolo(simbolo_aux, simbolo_aux.getId());
                if (existe != 0) SemErr("Ya existe el identitificador");
			} else {
				Get();
				if (StartOf(1)) {
					if (la.kind == 13) {
                        if (simbolo_aux.getId() != "main")
                    SynErr(36);
						Get();
					} else {
                        simbolo_aux2 = simbolo_aux;
                        simbolo_aux2.setTipo('m');
                        simbolo_aux2.setNumArgMetodo(0);
                        colaArgumento.clear();
                        ArgumentosDeclaracion();
                        simbolo_aux = simbolo_aux2;

					}
				}
                simbolo_aux2 = simbolo_aux;
				Esperado(25);
                int existe1 = tablasimbolos.InsertarSimbolo(simbolo_aux2, simbolo_aux2.getId());
                if (existe1 != 0)  SemErr("Ya existe un metodo con ese identificador en esta clase");
                tablasimbolos.CrearTablaHijo(simbolo_aux2.getId());
                int args = simbolo_aux2.getNumArgMetodo();
                Queue colaArgumento = simbolo_aux2.getColaArgumentos();
                Argumento arg;
                Inicializa_aux();
                while (args > 0){
                    arg = (Argumento) colaArgumento.poll();
                    simbolo_aux.setTipo(arg.getTipo());
                    simbolo_aux.setId(arg.getNombre());
                    int existe = tablasimbolos.InsertarSimbolo(simbolo_aux, simbolo_aux.getId());
                    if (existe != 0) SemErr("Existen dos parámetros con el mismo identificador");
                    args = args - 1;
                }
				Esperado(17);
				Miembros();
				Esperado(23);
                tablasimbolos.t_actual = tablasimbolos.t_actual.getSuperior();
                //Aqui deberia destruir esta tabla
			}
		}
	}

	static void Expresion() {
		Expresion2();
		Expresion1();
	}


    static void DeclaracionesArgumentos(){
        TiposSimples();
        char typo = simbolo_aux.getTipo();
        Esperado(1);
        argumento = new Argumento(typo, token.val);
        colaArgumento.offer(argumento);
        simbolo_aux2.setColaArgumentos(colaArgumento);
        simbolo_aux2.setNumArgMetodo(simbolo_aux2.getNumArgMetodo() + 1);
        
    }

	static void ArgumentosDeclaracion() {
		if (StartOf(1)) {
			DeclaracionesArgumentos();
			while (la.kind == 15) {
				Get();
				ArgumentosDeclaracion();
			}
		}
	}

	static void Miembros() {
		while (StartOf(2)) {
			if (StartOf(1)) {
				Declaraciones();
			} else {
				Sentencias();
			}
		}
	}




//    static void Asignaciones() {
//		Expect(1);
//		if (StartOf(4)) {
//			if (la.kind == 16) {
//				Get();
//				Expect(1);
//				if (la.kind == 19 || la.kind == 31) {
//					if (la.kind == 19) {
//						Get();
//						Argumentos();
//						Expect(25);
//						Expect(31);
//					} else {
//						Get();
//					}
//				}
//			} else if (la.kind == 1) {
//				Get();
//				Expect(31);
//			} else if (la.kind == 18) {
//				Get();
//				Expresion();
//				Expect(24);
//			} else {
//				Get();
//				if (StartOf(5)) {
//					if (StartOf(1)) {
//						ArgumentosDeclaracion();
//					} else {
//						Argumentos();
//					}
//				}
//				Expect(25);
//				if (la.kind == 17 || la.kind == 31) {
//					if (la.kind == 17) {
//						Get();
//						Miembros();
//						Expect(23);
//					} else {
//						Get();
//					}
//				}
//			}
//		}
//		ALLMetodo();
//	}


//    Asignaciones = ident ["." ident ["("Argumentos")" ";"] | ident ";" | "["Expresion"]" | "("[ArgumentosDeclaracion | Argumentos]")"["{"Miembros"}" |";"]] ALLMetodo

	static void Asignaciones() {
        //Inicializa_aux();
		Esperado(1);
        String nombre = simbolo.getId();
        simbolo_aux = tablasimbolos.Buscar(nombre);
        String nombre_class_asociada;
        TablaSimb tio = null;
        if (simbolo_aux == null){
            tio = tablasimbolos.BuscarTio(nombre);
            if (tio==null){
                SemErr("Identificador no declarado");
                return;
            }else{
                simbolo_aux = simbolo;
                simbolo_aux.setClaseRelacionada(nombre);
            }

        }

            nombre_class_asociada = simbolo_aux.getClaseRelacionada();
		if (StartOf(3)) {
			if (la.kind == 16) {
				Get();
				Esperado(1);

                if (simbolo_aux == null)
                    tio = tablasimbolos.BuscarTio(nombre_class_asociada);
                    if (tio == null) SemErr("El identificador no se corresponde con ninguna clase declarada");
                else{
                    simbolo_aux = tablasimbolos.BuscarEn(tio, simbolo.getId());
                     if (simbolo_aux == null)
                         SemErr("No existe ningún atributo o metodo en la clase " +nombre_class_asociada +" con ese identificador");
                     else
                         tipo_asig = simbolo_aux.getTipo();
                }
                if (la.kind == 19 || la.kind == 31) {
                   
				if (la.kind == 19) {
                    if (tipo_asig != 'm') SemErr("Sólo un método puede llevar argumentos");
                    else{
                        simbolo_aux2 = simbolo_aux;
                        colaArgumento = simbolo_aux2.getColaArgumentos();
                        Get();
                        Argumentos();
                        Esperado(25);
                        if (la.kind == 31)
                        Esperado(31);
                        else
                            if (la.kind != 15)
                                SemErr("Se esperaba ;");
                    }
                }
                if (la.kind == 31){
                   Esperado(31);

                }
                
                }
			} else if (la.kind == 1) {
                
                tio = tablasimbolos.BuscarTio(nombre);
                if (tio == null) SemErr("No existe ninguna clase declarada con ese identificador");
                else{
                Simbolo simb = new Simbolo(la.val, 'x',la.line);
                simb.setCol(la.col);
                simb.setPos(la.pos);
                simb.setClaseRelacionada(nombre);
                int existe = tablasimbolos.InsertarSimbolo(simb, la.val);
                if (existe != 0) SemErr("Existe otro elemento con el mismo identificador");
				Get();
				Esperado(31);
                }
			} else if (la.kind == 18) {
				Get();
				Expresion();
				Esperado(24);
			} else {
				Get();
				if (StartOf(4)) {
					if (StartOf(5)) {
						ArgumentosDeclaracion();
					} else {
						Argumentos();
					}
				}
				Esperado(25);
				if (la.kind == 17 || la.kind == 31) {
					if (la.kind == 17) {
						Get();
						Miembros();
						Esperado(23);
					} else {
						Get();
					}
				}
			}
		}
		ALLMetodo();
	}

	static void Argumentos() {

        argumento = colaArgumento.poll();
		if (StartOf(6)) {
            //expresion debe comprobar que si argumento no es vacio
            //su tipo de retorno debe coincidir con el tipo del argumento.
			Expresion();
			while (la.kind == 15) {
				Get();
				Argumentos();
			}
		}
	}

	static void ALLMetodo() {
		if (la.kind == 30) {
			Get();
			Expresion();
			Esperado(31);
		}
	}

	static void ES() {
		if (la.kind == 37) {
			Escribir();
		} else if (la.kind == 38) {
			Leer();
		} else SynErr(44);
	}

	static void Escribir() {
		Esperado(37);
		Esperado(19);
		if (StartOf(6)) {
			if (la.kind == 3) {
				Get();
			} else {
				Expresion();
			}
		}
		Esperado(25);
		Esperado(31);
	}

	static void Leer() {
		Esperado(38);
		Esperado(19);
		Expresion();
		Esperado(25);
		Esperado(31);
	}

	static void Retorno() {
		Esperado(39);
		if (StartOf(6)) {
			Expresion();
		}
		Esperado(31);
	}

	static void For() {
		Esperado(40);
		Esperado(19);
		Asignaciones();
		Expresion();
		Esperado(31);
		Asignaciones();
		Esperado(25);
		if (la.kind == 17) {
			Get();
			while (StartOf(7)) {
				Sentencias();
			}
			Esperado(23);
		} else if (StartOf(7)) {
			Sentencias();
		} else SynErr(45);
	}

	static void Sentencias() {
		if (la.kind == 1) {
			Asignaciones();
		} else if (la.kind == 39) {
			Retorno();
		} else if (la.kind == 37 || la.kind == 38) {
			ES();
		} else if (la.kind == 40) {
			For();
		} else SynErr(46);
	}

	static void Expresion2() {
		Expresion3();
		Expresion21();
	}

	static void Expresion1() {
		if (la.kind == 33) {
			Get();
			Expresion();
			Esperado(14);
			Expresion();
			Expresion1();
		}
	}

	static void Expresion3() {
		Expresion4();
		Expresion31();
	}

	static void Expresion21() {
		if (la.kind == 28) {
			Get();
			Expresion3();
			Expresion21();
		}
	}

	static void Expresion4() {
		if (la.kind == 21) {
			Get();
			Expresion4();
		} else if (StartOf(8)) {
			Expresion5();
		} else SynErr(47);
	}

	static void Expresion31() {
		if (la.kind == 22) {
			Get();
			Expresion4();
			Expresion31();
		}
	}

	static void Expresion5() {
		switch (la.kind) {
		case 19: {
			Get();
			Expresion();
			Esperado(25);
			break;
		}
		case 9: {
			Get();
			Esperado(1);
			Esperado(19);
			Argumentos();
			Esperado(25);
			break;
		}
		case 1: {
			Get();
			if (la.kind == 16 || la.kind == 18 || la.kind == 19) {
				if (la.kind == 16) {
					Get();
					Esperado(1);
					if (la.kind == 19) {
						Get();
						Argumentos();
						Esperado(25);
					}
				} else if (la.kind == 19) {
					Get();
					Argumentos();
					Esperado(25);
				} else {
					Get();
					Expresion();
					Esperado(24);
				}
			}
			break;
		}
		case 2: {
			Get();
			break;
		}
		case 3: {
			Get();
			break;
		}
		case 12: {
			Get();
			break;
		}
		case 7: {
			Get();
			break;
		}
		default: SynErr(48); break;
		}
	}



	public static void Parse() {
		la = new Token();
		la.val = "";
		Get();
		compilationunit();
		Esperado(0);

	}

	private static boolean[][] set = {
		{T,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x},
		{x,x,x,x, T,x,x,x, T,x,x,x, x,T,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,T,T, x,x,x,x, x,x,x},
		{x,T,x,x, T,x,x,x, T,x,x,x, x,T,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,T,T, x,T,T,T, T,x,x},
		{x,T,x,x, x,x,x,x, x,x,x,x, x,x,x,x, T,x,T,T, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x},
		{x,T,T,T, T,x,x,T, T,T,x,x, T,T,x,x, x,x,x,T, x,T,x,x, x,T,x,x, x,x,x,x, x,x,T,T, x,x,x,x, x,x,x},
		{x,x,x,x, T,x,x,x, T,x,x,x, x,T,x,x, x,x,x,x, x,x,x,x, x,T,x,x, x,x,x,x, x,x,T,T, x,x,x,x, x,x,x},
		{x,T,T,T, x,x,x,T, x,T,x,x, T,x,x,x, x,x,x,T, x,T,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x},
		{x,T,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,T,T,T, T,x,x},
		{x,T,T,T, x,x,x,T, x,T,x,x, T,x,x,x, x,x,x,T, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x}

	};

} // end Parser

/* pdt - considerable extension from here on */

class ErrorRec {
	public int line, col, num;
	public String str;
	public ErrorRec next;

	public ErrorRec(int l, int c, String s) {
		line = l; col = c; str = s; next = null;
	}

} // end ErrorRec

class Errors {

	public static int count = 0;                                     // number of errors detected
	public static String errMsgFormat = "file {0} : ({1}, {2}) {3}"; // 0=file 1=line, 2=column, 3=text
	static String fileName = "";
	static String listName = "";
	static boolean mergeErrors = false;
	static PrintWriter mergedList;

	static ErrorRec first = null, last;
	static boolean eof = false;

	static String getLine() {
		char ch, CR = '\r', LF = '\n';
		int l = 0;
		StringBuffer s = new StringBuffer();
		ch = (char) Buffer.Read();
		while (ch != Buffer.EOF && ch != CR && ch != LF) {
			s.append(ch); l++; ch = (char) Buffer.Read();
		}
		eof = (l == 0 && ch == Buffer.EOF);
		if (ch == CR) {  // check for MS-DOS
			ch = (char) Buffer.Read();
			if (ch != LF && ch != Buffer.EOF) Buffer.pos--;
		}
		return s.toString();
	}

	static private String Int(int n, int len) {
		String s = String.valueOf(n);
		int i = s.length(); if (len < i) len = i;
		int j = 0, d = len - s.length();
		char[] a = new char[len];
		for (i = 0; i < d; i++) a[i] = ' ';
		for (j = 0; i < len; i++) {a[i] = s.charAt(j); j++;}
		return new String(a, 0, len);
	}

	static void display(String s, ErrorRec e) {
		mergedList.print("**** ");
		for (int c = 1; c < e.col; c++)
			if (s.charAt(c-1) == '\t') mergedList.print("\t"); else mergedList.print(" ");
		mergedList.println("^ " + e.str);
	}

	public static void Init (String fn, String dir, boolean merge) {
		fileName = fn;
		listName = dir + "listing.txt";
		mergeErrors = merge;
		if (mergeErrors)
			try {
				mergedList = new PrintWriter(new BufferedWriter(new FileWriter(listName, false)));
			} catch (IOException e) {
				Errors.Exception("-- could not open " + listName);
			}
	}

	public static void Summarize () {
		if (mergeErrors) {
			ErrorRec cur = first;
			Buffer.setPos(0);
			int lnr = 1;
			String s = getLine();
			while (!eof) {
				mergedList.println(Int(lnr, 4) + " " + s);
				while (cur != null && cur.line == lnr) {
					display(s, cur); cur = cur.next;
				}
				lnr++; s = getLine();
			}
			if (cur != null) {
				mergedList.println(Int(lnr, 4));
				while (cur != null) {
					display(s, cur); cur = cur.next;
				}
			}
			mergedList.println();
			mergedList.println(count + " errors detected");
			mergedList.close();
		}
		switch (count) {
			case 0 : System.out.println("Parsed correctly"); break;
			case 1 : System.out.println("1 error detected"); break;
			default: System.out.println(count + " errors detected"); break;
		}
		if (count > 0 && mergeErrors) System.out.println("see " + listName);
	}

	public static void storeError (int line, int col, String s) {
		if (mergeErrors) {
			ErrorRec latest = new ErrorRec(line, col, s);
			if (first == null) first = latest; else last.next = latest;
			last = latest;
		} else printMsg(fileName, line, col, s);
	}

	public static void SynErr (int line, int col, int n) {
		String s;
		switch (n) {
			case 0: s = "EOF Esperadoed"; break;
			case 1: s = "ident expected"; break;
			case 2: s = "enteros expected"; break;
			case 3: s = "cadenaCar expected"; break;
			case 4: s = "boolean expected"; break;
			case 5: s = "char expected"; break;
			case 6: s = "class expected"; break;
			case 7: s = "false expected"; break;
			case 8: s = "int expected"; break;
			case 9: s = "new expected"; break;
			case 10: s = "short expected"; break;
			case 11: s = "static expected"; break;
			case 12: s = "true expected"; break;
			case 13: s = "void expected"; break;
			case 14: s = "dosPuntos expected"; break;
			case 15: s = "comma expected"; break;
			case 16: s = "punto expected"; break;
			case 17: s = "llaveIzda expected"; break;
			case 18: s = "corcheteIzda expected"; break;
			case 19: s = "parentesisIzda expected"; break;
			case 20: s = "menos expected"; break;
			case 21: s = "not expected"; break;
			case 22: s = "mas expected"; break;
			case 23: s = "llaveDer expected"; break;
			case 24: s = "corcheteDer expected"; break;
			case 25: s = "parentesisDer expected"; break;
			case 26: s = "multiplicacion expected"; break;
			case 27: s = "div expected"; break;
			case 28: s = "menor expected"; break;
			case 29: s = "mayor expected"; break;
			case 30: s = "igual expected"; break;
			case 31: s = "puntoComa expected"; break;
			case 32: s = "doblesComillas expected"; break;
			case 33: s = "interrogacion expected"; break;
			case 34: s = "\"public\" expected"; break;
			case 35: s = "\"private\" expected"; break;
			case 36: s = "\"main\" expected"; break;
			case 37: s = "\"print\" expected"; break;
			case 38: s = "\"read\" expected"; break;
			case 39: s = "\"return\" expected"; break;
			case 40: s = "\"for\" expected"; break;
			case 41: s = "??? expected"; break;
			case 42: s = "invalid TiposSimples"; break;
			case 43: s = "invalid Declaraciones"; break;
			case 44: s = "invalid ES"; break;
			case 45: s = "invalid For"; break;
			case 46: s = "invalid Sentencias"; break;
			case 47: s = "invalid Expresion4"; break;
			case 48: s = "invalid Expresion5"; break;
			default: s = "error " + n; break;
		}
		storeError(line, col, s);
		count++;
	}

	public static void SemErr (int line, int col, int n) {
		storeError(line, col, ("error " + n));
		count++;
	}

	public static void Error (int line, int col, String s) {
		storeError(line, col, s);
		count++;
	}

	public static void Warn (int line, int col, String s) {
		storeError(line, col, s);
	}

	public static void Exception (String s) {
		System.out.println(s);
		System.exit(1);
	}

	private static void printMsg(String fileName, int line, int column, String msg) {
		StringBuffer b = new StringBuffer(errMsgFormat);
		int pos = b.indexOf("{0}");
		if (pos >= 0) { b.replace(pos, pos+3, fileName); }
		pos = b.indexOf("{1}");
		if (pos >= 0) { b.delete(pos, pos+3); b.insert(pos, line); }
		pos = b.indexOf("{2}");
		if (pos >= 0) { b.delete(pos, pos+3); b.insert(pos, column); }
		pos = b.indexOf("{3}");
		if (pos >= 0) b.replace(pos, pos+3, msg);
		System.out.println(b.toString());
	}

} // end Errors
